home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / net / ds5000.md / netLEXmit.c < prev   
C/C++ Source or Header  |  1992-12-18  |  22KB  |  787 lines

  1. /* 
  2.  * netLEXmit.c --
  3.  *
  4.  *    Routines to transmit packets on the LANCE interface.
  5.  *
  6.  * Copyright 1988 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  *
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/net/ds5000.md/netLEXmit.c,v 9.14 92/06/25 17:24:19 jhh Exp $ SPRITE (Berkeley)";
  19. #endif
  20.  
  21. #include <sprite.h>
  22. #include <sys.h>
  23. #include <netLEInt.h>
  24. #include <vm.h>
  25. #include <vmMach.h>
  26. #include <list.h>
  27. #include <sync.h>
  28. #include <machMon.h>
  29.  
  30. /*
  31.  * Macros to step ring pointers.
  32.  */
  33.  
  34. #define    NEXT_SEND(p)    ( ((p+1) > statePtr->xmitDescLastPtr) ? \
  35.                 statePtr->xmitDescFirstPtr : \
  36.                 (p+1))
  37. #define    PREV_SEND(p)    ( ((p-1) < statePtr->xmitDescFirstPtr) ? \
  38.                 statePtr->xmitDescLastPtr : \
  39.                 (p-1))
  40. static    ReturnStatus    OutputPacket _ARGS_((Net_EtherHdr *etherHdrPtr,
  41.                 Net_ScatterGather *scatterGatherPtr,
  42.                 int scatterGatherLength,
  43.                 NetLEState *statePtr));
  44. static    void        AllocateXmitMem _ARGS_((NetLEState *statePtr));
  45.  
  46. char    foo[NET_ETHER_MAX_BYTES];
  47.  
  48. /*
  49.  *----------------------------------------------------------------------
  50.  *
  51.  * OutputPacket --
  52.  *
  53.  *    Assemble and output the packet in the given scatter/gather element.
  54.  *    The ethernet header contains the address of the destination host
  55.  *    and the higher level protocol type already.
  56.  *
  57.  * Results:
  58.  *    FAILURE if something went wrong.
  59.  *
  60.  * Side effects:
  61.  *    Transmit command list is modified to contain the packet.
  62.  *
  63.  *----------------------------------------------------------------------
  64.  */
  65.  
  66. static ReturnStatus
  67. OutputPacket(etherHdrPtr, scatterGatherPtr, scatterGatherLength, statePtr)
  68.     Net_EtherHdr        *etherHdrPtr;    /* Ethernet header of packet.*/
  69.     register    Net_ScatterGather       *scatterGatherPtr; /* Data portion of
  70.                                 * packet. */
  71.  
  72.     int            scatterGatherLength;    /* Length of data portion 
  73.                          * gather array. */
  74.     NetLEState        *statePtr;        /* The interface state. */
  75. {
  76.     register volatile NetLEXmitMsgDesc    *descPtr;
  77.     register    char            *firstBufferPtr; 
  78.     Address                bufPtr;
  79.     int                    bufCount;
  80.     int                    totalLength;
  81.     int                    length;
  82.     int                    amountNeeded;
  83. #if defined(sun3) || defined(sun4)
  84.     Net_ScatterGather            newScatGathArr[NET_LE_NUM_XMIT_BUFFERS];
  85.     register Boolean            reMapped = FALSE;
  86. #endif
  87.     int                    i;
  88.  
  89.     descPtr = statePtr->xmitDescNextPtr;
  90.  
  91.     /*
  92.      * Do some sanity checks.
  93.      */
  94.     if (NetBfByteTest(descPtr->bits1, ChipOwned, 1)) {
  95.     printf("LE ethernet: Transmit buffer owned by chip.\n");
  96.     return (FAILURE);
  97.     }
  98.  
  99.     statePtr->transmitting = TRUE;
  100.     statePtr->curScatGathPtr = scatterGatherPtr;
  101.     firstBufferPtr = statePtr->firstDataBuffer;
  102.  
  103.     /*
  104.      * Add the first data buffer to the ring.
  105.      */
  106.     descPtr->bufAddrLow = NET_LE_TO_CHIP_ADDR_LOW(firstBufferPtr);
  107.     descPtr->bufAddrHigh = NET_LE_TO_CHIP_ADDR_HIGH(firstBufferPtr);
  108.     NetBfByteSet(descPtr->bits1, StartOfPacket, 1);
  109.     NetBfByteSet(descPtr->bits1, EndOfPacket, 0);
  110.  
  111.     /*
  112.      * Since the first part of a packet is always the ethernet header that
  113.      * is less than NET_LE_MIN_FIRST_BUFFER_SIZE we must use the 
  114.      * firstDataBuffer to build the first buffer of mimumum allowable size.
  115.      */
  116.  
  117.  
  118.     descPtr->bufferSize = -NET_LE_MIN_FIRST_BUFFER_SIZE; /* May be wrong 
  119.                               * for small 
  120.                               * packets. 
  121.                               */
  122.  
  123.     /* 
  124.      * First copy in the header making sure the source address field is set
  125.      * correctly. (Such a fancy chip and it won't even set the source 
  126.      * address
  127.      * of the header for us.)
  128.      */
  129.  
  130.     (* ((Net_EtherHdr *) firstBufferPtr)) = *etherHdrPtr;
  131.  
  132.     ((Net_EtherHdr *) firstBufferPtr)->source = statePtr->etherAddress;
  133.  
  134.     firstBufferPtr += sizeof(Net_EtherHdr);
  135.  
  136.     if (NET_LE_COPY_PACKET) {
  137.     totalLength = sizeof(Net_EtherHdr);
  138.     for (i = 0; i < scatterGatherLength; i++) {
  139.         totalLength += scatterGatherPtr[i].length;
  140.     } 
  141.     if (totalLength <= NET_ETHER_MAX_BYTES) {
  142.         Net_GatherCopy(scatterGatherPtr, scatterGatherLength, 
  143.         firstBufferPtr);
  144.         descPtr->bufferSize = -totalLength;
  145.     } else {
  146.         printf("OutputPacket: packet too large (%d)\n", totalLength);
  147.         for (i = 0; i < scatterGatherLength; i++) {
  148.         printf("\t Buffer %d: %d\n", i, scatterGatherPtr[i].length);
  149.         }
  150.         return FAILURE;
  151.     }
  152.     } else {
  153.  
  154.     
  155.     /*
  156.      * Then copy enough data to bring buffer up to size.
  157.      */
  158.     
  159.     totalLength = sizeof(Net_EtherHdr);
  160.     
  161.     bufCount = 0;
  162.     for (bufCount = 0; bufCount < scatterGatherLength; 
  163.                 bufCount++,scatterGatherPtr++ ) {
  164.     
  165.         /*
  166.          * If is an empty buffer then skip it.
  167.          */
  168.     
  169.         length = scatterGatherPtr->length;
  170.         if (length == 0) {
  171.         continue;
  172.         }
  173.     
  174.         bufPtr = scatterGatherPtr->bufAddr;
  175.     
  176.         /*
  177.          * Compute the amount of data needed in the first buffer to make it
  178.          * a minumum size.
  179.          */
  180.     
  181.         amountNeeded = NET_LE_MIN_FIRST_BUFFER_SIZE - totalLength;
  182.         if (amountNeeded > 0 ) {
  183.         /*
  184.          * Still need more padding in first buffer.
  185.          */
  186.         if (length <= amountNeeded) {
  187.              /*
  188.               * Needs this entire length.
  189.               */
  190.              bcopy(bufPtr, firstBufferPtr, length);
  191.              totalLength += length;
  192.              firstBufferPtr += length;
  193.              /*
  194.               * Get the next segment of the scatter.
  195.               */
  196.              continue;
  197.         } else {
  198.             /*
  199.              * Needs only part of this buffer.
  200.              */
  201.              bcopy(bufPtr, firstBufferPtr, amountNeeded);
  202.              totalLength += amountNeeded;
  203.              /*
  204.               * Update the length and address for insertion into the
  205.               * buffer ring. firstBufferPtr is not used anymore in this
  206.               * loop.
  207.               */
  208.              length -= amountNeeded;
  209.              bufPtr += amountNeeded;
  210.              if (length == 0) {
  211.                 continue;
  212.              }
  213.     
  214.         }
  215.          }
  216. #if defined(sun3) || defined(sun4)
  217.         if (!reMapped) { 
  218.         /*
  219.          * Remap the packet into network addressible memory.
  220.          */
  221.         VmMach_NetMapPacket(scatterGatherPtr, 
  222.             scatterGatherLength-bufCount, newScatGathArr);
  223.         bufPtr = newScatGathArr->bufAddr + 
  224.                 (bufPtr - scatterGatherPtr->bufAddr);
  225.         scatterGatherPtr = newScatGathArr;
  226.         reMapped = TRUE;
  227.         }
  228. #endif
  229.         /*
  230.          * Add bufPtr of length length to the next buffer of the chain.
  231.          */
  232.         descPtr = NEXT_SEND(descPtr);
  233.         if (NetBfByteTest(descPtr->bits1, ChipOwned, 1)) {
  234.         /*
  235.          * Along as we only transmit one packet at a time, a buffer
  236.          * own by the chip is a serious problem.
  237.          */
  238.         printf("LE ethernet: Transmit buffer owned by chip.\n");
  239.         return (FAILURE);
  240.         }
  241.         descPtr->bufAddrLow = NET_LE_TO_CHIP_ADDR_LOW(bufPtr);
  242.         descPtr->bufAddrHigh = NET_LE_TO_CHIP_ADDR_HIGH(bufPtr);
  243.         NetBfByteSet(descPtr->bits1, StartOfPacket, 0);
  244.         NetBfByteSet(descPtr->bits1, EndOfPacket, 0);
  245.         descPtr->bufferSize = -length;
  246.  
  247.         totalLength += length;
  248.     }
  249.     }
  250.  
  251.     /*
  252.      * See if we need to update the size of the first buffer.
  253.      */
  254.  
  255.     if (totalLength < NET_LE_MIN_FIRST_BUFFER_SIZE) {
  256.     /*
  257.      * Since totalLength < NET_LE_MIN_FIRST_BUFFER_SIZE, descPtr should
  258.      * still point at the buffer desciptor for the first block.
  259.      * Just update its size. If the size is less than the minimum possible
  260.      * length, increase the length and send the garbage in the buffer.
  261.      */
  262.     descPtr->bufferSize = -totalLength;
  263.     if (totalLength < NET_ETHER_MIN_BYTES) {
  264.         descPtr->bufferSize = -NET_ETHER_MIN_BYTES;
  265.     } 
  266.     }
  267.  
  268.     /*
  269.      * Finish off the packet.
  270.      */
  271.  
  272.     NetBfByteSet(descPtr->bits1, EndOfPacket, 1);
  273.  
  274.     /*
  275.      * Change the ownership to the chip. Avoid race conditions by doing it
  276.      * with the last buffer first.
  277.      */
  278.  
  279.     while (TRUE) {
  280.     NetBfByteSet(descPtr->bits1, ChipOwned, 1);
  281.     if (descPtr == statePtr->xmitDescNextPtr) {
  282.         break;
  283.     }
  284.     descPtr = PREV_SEND(descPtr);
  285.     }
  286.  
  287.     /*
  288.      * Give the chip a little kick.
  289.      */
  290.     NetBfShortSet(statePtr->regPortPtr->addrPort, AddrPort, NET_LE_CSR0_ADDR);
  291.     Mach_EmptyWriteBuffer();
  292.     statePtr->regPortPtr->dataPort = 
  293.         (NET_LE_CSR0_XMIT_DEMAND | NET_LE_CSR0_INTR_ENABLE);
  294.     return (SUCCESS);
  295.  
  296. }
  297.  
  298.  
  299. /*
  300.  *----------------------------------------------------------------------
  301.  *
  302.  * AllocateXmitMem --
  303.  *
  304.  *    Allocate kernel memory for transmission ring.    
  305.  *
  306.  * Results:
  307.  *    None.
  308.  *
  309.  * Side effects:
  310.  *    Device state structure is updated.
  311.  *
  312.  *----------------------------------------------------------------------
  313.  */
  314.  
  315. static void
  316. AllocateXmitMem(statePtr)
  317.     NetLEState        *statePtr;     /* State of the interface. */
  318. {
  319.     unsigned int    memBase;    
  320.  
  321.     /*
  322.      * Allocate the ring of transmission buffer descriptors.  
  323.      * The ring must start on 8-byte boundary.  
  324.      */
  325.     memBase = (unsigned int) BufAlloc(statePtr, 
  326.     (NET_LE_NUM_XMIT_BUFFERS * sizeof(NetLEXmitMsgDesc)) + 8);
  327.     /*
  328.      * Insure ring starts on 8-byte boundary.
  329.      */
  330.     if (memBase & 0x7) {
  331.     memBase = (memBase + 8) & ~0x7;
  332.     }
  333.     statePtr->xmitDescFirstPtr = (NetLEXmitMsgDesc *) memBase;
  334.  
  335.     /*
  336.      * Allocate the first buffer for a packet.
  337.      */
  338.     statePtr->firstDataBuffer = BufAlloc(statePtr, ((NET_LE_COPY_PACKET) ? 
  339.     NET_ETHER_MAX_BYTES : NET_LE_MIN_FIRST_BUFFER_SIZE));
  340.     statePtr->xmitMemAllocated = TRUE;
  341.     return;
  342. }
  343.  
  344. /*
  345.  *----------------------------------------------------------------------
  346.  *
  347.  * NetLEXmitInit --
  348.  *
  349.  *    Initialize the transmission queue structures.  This includes setting
  350.  *    up the transmission ring buffers.
  351.  *
  352.  * Results:
  353.  *    None.
  354.  *
  355.  * Side effects:
  356.  *    The transmission ring is initialized.
  357.  *
  358.  *----------------------------------------------------------------------
  359.  */
  360.  
  361. void
  362. NetLEXmitInit(statePtr)
  363.     NetLEState        *statePtr;     /* State of the interface. */
  364. {
  365.     int         bufNum;
  366.     volatile NetLEXmitMsgDesc    *descPtr;
  367.  
  368.  
  369.     if (!statePtr->xmitMemAllocated) {
  370.     AllocateXmitMem(statePtr);
  371.     }
  372.     statePtr->xmitMemInitialized = TRUE;
  373.  
  374.     /*
  375.      * Initialize the state structure to point to the ring. xmitDescFirstPtr
  376.      * is set by AllocateXmitMem() and never moved.
  377.      */
  378.     statePtr->xmitDescLastPtr = 
  379.         &(statePtr->xmitDescFirstPtr[NET_LE_NUM_XMIT_BUFFERS-1]);
  380.     statePtr->xmitDescNextPtr = statePtr->xmitDescFirstPtr;
  381.  
  382.     descPtr = statePtr->xmitDescFirstPtr;
  383.     for (bufNum = 0; bufNum < NET_LE_NUM_XMIT_BUFFERS; bufNum++, descPtr++) { 
  384.     bzero((char *) descPtr, sizeof(NetLEXmitMsgDesc));
  385.     }
  386.     statePtr->transmitting = FALSE;
  387.     statePtr->curScatGathPtr = (Net_ScatterGather *) NIL;
  388.     return;
  389. }
  390.  
  391.  
  392. /*
  393.  *----------------------------------------------------------------------
  394.  *
  395.  * NetLEXmitDone --
  396.  *
  397.  *    This routine will process a completed transmit command.  It will
  398.  *    check for errors and update the transmission ring pointers.
  399.  *
  400.  * Results:
  401.  *    FAILURE if problem is found.
  402.  *
  403.  * Side effects:
  404.  *    None.
  405.  *
  406.  *----------------------------------------------------------------------
  407.  */
  408.  
  409. ReturnStatus
  410. NetLEXmitDone(statePtr)
  411.     NetLEState        *statePtr;     /* State of the interface. */
  412. {
  413.     register    volatile NetXmitElement         *xmitElementPtr;
  414.     register    volatile NetLEXmitMsgDesc    *descPtr;
  415.     ReturnStatus            status;
  416.     char                *buffer; 
  417.  
  418.     descPtr = statePtr->xmitDescNextPtr;
  419.  
  420.     /*
  421.      * If there is nothing that is currently being sent then something is
  422.      * wrong.
  423.      */
  424.     if (statePtr->curScatGathPtr == (Net_ScatterGather *) NIL) {
  425.     printf( "NetLEXmitDone: No current packet\n.");
  426.     status = FAILURE;
  427.     goto exit;
  428.     }
  429.  
  430.     if (NetBfByteTest(descPtr->bits1, ChipOwned, 1)) {
  431.     printf("LE ethernet: Bogus xmit interrupt. Buffer owned by chip.\n");
  432.     status = FAILURE;
  433.     goto exit;
  434.     }
  435.     if (NetBfByteTest(descPtr->bits1, StartOfPacket, 0)) {
  436.     printf("LE ethernet: Bogus xmit interrupt. Buffer not start of packet.\n");
  437.     status = FAILURE;
  438.     goto exit;
  439.     }
  440.  
  441.     /*
  442.      * Check for errors.
  443.      */
  444.     while (TRUE) {
  445.  
  446.     if (NetBfByteTest(descPtr->bits1, Error, 1)) {
  447.         statePtr->stats.xmitPacketsDropped++;
  448.         if (NetBfShortTest(descPtr->bits2, LostCarrier, 1)) {
  449.         printf("LE ethernet: Lost carrier.\n");
  450.         }
  451.         /*
  452.          * Lost of carrier seems to also causes late collision.
  453.          * Print only one of the messages.
  454.          */
  455.         if ((NetBfShortTest(descPtr->bits2, LateCollision, 1)) &&
  456.         (NetBfShortTest(descPtr->bits2, LostCarrier, 0))) {
  457.         statePtr->lateCollisions++;
  458.         if ((statePtr->lateCollisions % 100) == 0) {
  459.             printf("LE ethernet: 100 transmit late collisions.\n");
  460.         }
  461.         }
  462.         if (NetBfShortTest(descPtr->bits2, RetryError, 1)) {
  463.         statePtr->stats.xmitCollisionDrop++;
  464.         statePtr->stats.collisions += 16;
  465.         if ((statePtr->stats.xmitCollisionDrop % 100) == 0) {
  466.             printf(
  467.         "LE ethernet: 100 packets dropped due to too many collisions.\n");
  468.         }
  469.         }
  470.         if (NetBfShortTest(descPtr->bits2, UnderflowError, 1)) {
  471.         printf("LE ethernet: Memory underflow error.\n");
  472.         status = FAILURE;
  473.         goto exit;
  474.         }
  475.     }
  476.     if (NetBfShortTest(descPtr->bits2, XmitBufferError, 1)) {
  477.         printf("LE ethernet: Transmit buffering error.\n");
  478.         status = FAILURE;
  479.         goto exit;
  480.     }
  481.     if (NetBfByteTest(descPtr->bits1, OneRetry, 1)) {
  482.         statePtr->stats.collisions++;
  483.     }
  484.     if (NetBfByteTest(descPtr->bits1, Retries, 1)) {
  485.         /*
  486.          * Two is more than one.  
  487.          */
  488.         statePtr->stats.collisions += 2;    /* Only a guess. */
  489.     }
  490.  
  491.     buffer = (char *) NET_LE_FROM_CHIP_ADDR(statePtr, 
  492.         descPtr->bufAddrHigh, descPtr->bufAddrLow);
  493.  
  494.     if (NetBfByteTest(descPtr->bits1, EndOfPacket, 1)) {
  495.         break;
  496.     }
  497.  
  498.     descPtr = NEXT_SEND(descPtr);
  499.     if (descPtr == statePtr->xmitDescNextPtr) {
  500.         panic("LE ethernet: Transmit ring with no end of packet.\n");
  501.     }
  502.     if (NetBfByteTest(descPtr->bits1, ChipOwned, 1)) {
  503.         printf("LE ethernet: Transmit Buffer owned by chip.\n");
  504.         status = FAILURE;
  505.         goto exit;
  506.     }
  507.     }
  508.  
  509.     statePtr->stats.packetsSent++;
  510.  
  511.     /*
  512.      * Update the ring pointer to point at the next buffer to use.
  513.      */
  514.  
  515.     statePtr->xmitDescNextPtr = NEXT_SEND(descPtr);
  516.  
  517.     /*
  518.      * Mark the packet as done.
  519.      */
  520.     statePtr->curScatGathPtr->done = TRUE;
  521.     if (statePtr->curScatGathPtr->mutexPtr != (Sync_Semaphore *) NIL) {
  522.     NetOutputWakeup(statePtr->curScatGathPtr->mutexPtr);
  523.     }
  524.  
  525.     /*
  526.      * If there are more packets to send then send the first one on
  527.      * the queue.  Otherwise there is nothing being transmitted.
  528.      */
  529.     status = SUCCESS;
  530.     if (statePtr->resetPending == TRUE) {
  531.     goto exit;
  532.     }
  533.     if (!List_IsEmpty(statePtr->xmitList)) {
  534.     xmitElementPtr = (NetXmitElement *) List_First(statePtr->xmitList);
  535.     status = OutputPacket(xmitElementPtr->etherHdrPtr,
  536.              xmitElementPtr->scatterGatherPtr,
  537.              xmitElementPtr->scatterGatherLength, statePtr);
  538.     List_Move((List_Links *) xmitElementPtr, 
  539.           LIST_ATREAR(statePtr->xmitFreeList));
  540.     } else {
  541.     statePtr->transmitting = FALSE;
  542.     statePtr->curScatGathPtr = (Net_ScatterGather *) NIL;
  543.     }
  544. exit:
  545.     /*
  546.      * This assumes that whatever calls us will reset the chip if we return
  547.      * anything other than SUCCESS.  This way we avoid resetting the chip 
  548.      * twice in a row.
  549.      */
  550.     if ((statePtr->resetPending == TRUE) && (status == SUCCESS)) {
  551.     statePtr->transmitting = FALSE;
  552.     NetLEReset(statePtr->interPtr);
  553.     }
  554.     if (status != SUCCESS) {
  555.     statePtr->transmitting = FALSE;
  556.     }
  557.     return (status);
  558. }
  559.  
  560.  
  561. /*
  562.  *----------------------------------------------------------------------
  563.  *
  564.  * NetLEOutput --
  565.  *
  566.  *    Output a packet.  The procedure is to either put the packet onto the 
  567.  *    queue of outgoing packets if packets are already being sent, or 
  568.  *    otherwise to send the packet directly.  The elements of the scatter 
  569.  *    array which come into this routine must satisfy the following two 
  570.  *    properties:
  571.  *
  572.  *
  573.  * Results:
  574.  *    SUCCESS if the packet was queued to the chip correctly, otherwise
  575.  *    a standard Sprite error code.
  576.  *
  577.  * Side effects:
  578.  *    Queue of packets modified.
  579.  *
  580.  *----------------------------------------------------------------------
  581.  */
  582.  
  583. ReturnStatus
  584. NetLEOutput(interPtr, hdrPtr, scatterGatherPtr, scatterGatherLength, rpc,
  585.         statusPtr)
  586.     Net_Interface    *interPtr;    /* The network interface. */
  587.     Address        hdrPtr;        /* Packet header. */
  588.     register    Net_ScatterGather    *scatterGatherPtr; /* Data portion of 
  589.                                 * the packet. */
  590.     int            scatterGatherLength;    /* Length of data portion gather
  591.                          * array. */
  592.     Boolean        rpc;            /* Is this an RPC packet? */
  593.     ReturnStatus    *statusPtr;        /* Status from sending packet.*/
  594. {
  595.     register    NetXmitElement        *xmitPtr;
  596.     ReturnStatus            status;
  597.     NetLEState                *statePtr;
  598.     Net_EtherHdr            *etherHdrPtr = (Net_EtherHdr *) hdrPtr;
  599.     Boolean                restart = FALSE;
  600.  
  601.     statePtr = (NetLEState *) interPtr->interfaceData;
  602.     MASTER_LOCK(&interPtr->mutex);
  603.  
  604.     statePtr->stats.packetsOutput++;
  605.  
  606.     /*
  607.      * Verify that the scatter gather array is not too large.  There is a fixed
  608.      * upper bound because the list of transmit buffers is preallocated.
  609.      */
  610.  
  611.     if (scatterGatherLength >= NET_LE_NUM_XMIT_BUFFERS) {
  612.     scatterGatherPtr->done = TRUE;
  613.  
  614.     printf("LE ethernet: Packet in too many pieces\n");
  615.     status = FAILURE;
  616.     goto exit;
  617.     }
  618.  
  619.  
  620.     /*
  621.      * See if the packet is for us.  In this case just copy in the packet
  622.      * and call the higher level routine.
  623.      */
  624.  
  625.     if (!Net_EtherAddrCmp(statePtr->etherAddress, etherHdrPtr->destination)) {
  626.     int i, length;
  627.  
  628.         length = sizeof(Net_EtherHdr);
  629.         for (i = 0; i < scatterGatherLength; i++) {
  630.             length += scatterGatherPtr[i].length;
  631.         }
  632.  
  633.         if (length <= NET_ETHER_MAX_BYTES) {
  634.         register Address bufPtr;
  635.  
  636.         etherHdrPtr->source = statePtr->etherAddress;
  637.  
  638.         bufPtr = (Address)statePtr->loopBackBuffer;
  639.         bcopy((Address)etherHdrPtr, bufPtr, sizeof(Net_EtherHdr));
  640.         bufPtr += sizeof(Net_EtherHdr);
  641.             Net_GatherCopy(scatterGatherPtr, scatterGatherLength, bufPtr);
  642.  
  643.         Net_Input(interPtr, (Address)statePtr->loopBackBuffer, length);
  644.         }
  645.  
  646.         scatterGatherPtr->done = TRUE;
  647.  
  648.     status = SUCCESS;
  649.     if (statusPtr != (ReturnStatus *) NIL) {
  650.         *statusPtr = SUCCESS;
  651.     }
  652.     goto exit;
  653.     }
  654.  
  655.     /*
  656.      * If no packet is being sent then go ahead and send this one.
  657.      */
  658.  
  659.     if (!statePtr->transmitting) {
  660.     status = 
  661.         OutputPacket(etherHdrPtr, scatterGatherPtr, scatterGatherLength,
  662.             statePtr);
  663.     if (status != SUCCESS) {
  664.         restart = TRUE;
  665.     } else if (statusPtr != (ReturnStatus *) NIL) {
  666.         *statusPtr = SUCCESS;
  667.     }
  668.     goto exit;
  669.     }
  670.     /*
  671.      * There is a packet being sent so this packet has to be put onto the
  672.      * transmission queue.  Get an element off of the transmission free list.  
  673.      * If none available then drop the packet.
  674.      */
  675.  
  676.     if (List_IsEmpty(statePtr->xmitFreeList)) {
  677.         scatterGatherPtr->done = TRUE;
  678.     status = FAILURE;
  679.     goto exit;
  680.     }
  681.  
  682.     xmitPtr = (NetXmitElement *) List_First((List_Links *) statePtr->xmitFreeList);
  683.  
  684.     List_Remove((List_Links *) xmitPtr);
  685.  
  686.     /*
  687.      * Initialize the list element.
  688.      */
  689.  
  690.     xmitPtr->etherHdrPtr = etherHdrPtr;
  691.     xmitPtr->scatterGatherPtr = scatterGatherPtr;
  692.     xmitPtr->scatterGatherLength = scatterGatherLength;
  693.  
  694.     /* 
  695.      * Put onto the transmission queue.
  696.      */
  697.  
  698.     List_Insert((List_Links *) xmitPtr, LIST_ATREAR(statePtr->xmitList)); 
  699.  
  700.     if (statusPtr != (ReturnStatus *) NIL) {
  701.     *statusPtr = SUCCESS;
  702.     }
  703.     status = SUCCESS;
  704. exit:
  705.     MASTER_UNLOCK(&interPtr->mutex);
  706.     if (restart) {
  707.     NetLERestart(interPtr);
  708.     }
  709.     return SUCCESS;
  710. }
  711.  
  712.  
  713. /*
  714.  *----------------------------------------------------------------------
  715.  *
  716.  * NetLEXmitDrop --
  717.  *
  718.  *    Drop the current packet.  Called at the beginning of the
  719.  *    restart sequence, before curScatGathPtr is reset to NIL.
  720.  *
  721.  * Results:
  722.  *    None.
  723.  *
  724.  * Side effects:
  725.  *    Current scatter gather pointer is reset and processes waiting
  726.  *    for synchronous output are notified.
  727.  *
  728.  *----------------------------------------------------------------------
  729.  */
  730. void
  731. NetLEXmitDrop(statePtr)
  732.     NetLEState        *statePtr;     /* State of the interface. */
  733. {
  734.     if (statePtr->curScatGathPtr != (Net_ScatterGather *) NIL) {
  735.     statePtr->curScatGathPtr->done = TRUE;
  736.     if (statePtr->curScatGathPtr->mutexPtr != (Sync_Semaphore *) NIL) {
  737.         NetOutputWakeup(statePtr->curScatGathPtr->mutexPtr);
  738.     }
  739.     statePtr->curScatGathPtr = (Net_ScatterGather *) NIL;
  740.     }
  741.     statePtr->transmitting = FALSE;
  742.     return;
  743. }
  744.  
  745. /*
  746.  *----------------------------------------------------------------------
  747.  *
  748.  * NetLEXmitRestart --
  749.  *
  750.  *    Restart transmission of packets at the end of the restart
  751.  *    sequence, after a chip reset.
  752.  *
  753.  * Results:
  754.  *    None.
  755.  *
  756.  * Side effects:
  757.  *    Output queue started up.
  758.  *
  759.  *----------------------------------------------------------------------
  760.  */
  761. void
  762. NetLEXmitRestart(statePtr)
  763.     NetLEState        *statePtr;     /* State of the interface. */
  764. {
  765.     NetXmitElement    *xmitElementPtr;
  766.     ReturnStatus    status;
  767.  
  768.     /*
  769.      * Start output if there are any packets queued up.
  770.      */
  771.     if (!List_IsEmpty(statePtr->xmitList)) {
  772.     xmitElementPtr = (NetXmitElement *) List_First(statePtr->xmitList);
  773.     status = OutputPacket(xmitElementPtr->etherHdrPtr,
  774.              xmitElementPtr->scatterGatherPtr,
  775.              xmitElementPtr->scatterGatherLength, statePtr);
  776.     if (status != SUCCESS) {
  777.         panic("LE ethernet: Can not output first packet on restart.\n");
  778.     }
  779.     List_Move((List_Links *) xmitElementPtr, 
  780.           LIST_ATREAR(statePtr->xmitFreeList));
  781.     } else {
  782.     statePtr->transmitting = FALSE;
  783.     statePtr->curScatGathPtr = (Net_ScatterGather *) NIL;
  784.     }
  785.     return;
  786. }
  787.